package start.spring.basic.flowable.service.biz.leave.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

import cn.hutool.core.util.ObjectUtil;
import start.spring.basic.enums.ServiceEnum;
import start.spring.basic.flowable.common.ProcessConstants;
import start.spring.basic.flowable.dao.BizLeaveMapper;
import start.spring.basic.flowable.dao.WfApplyRecordMapper;
import start.spring.basic.flowable.entity.BizLeave;
import start.spring.basic.flowable.entity.WfApplyRecord;
import start.spring.basic.flowable.entity.WfCategory;
import start.spring.basic.flowable.entity.WfDeployForm;
import start.spring.basic.flowable.enums.flowable.ApprovalStatus;
import start.spring.basic.flowable.service.FlowableBaseServiceImpl;
import start.spring.basic.flowable.service.biz.leave.IBizLeaveService;
import start.spring.basic.flowable.service.category.IWfCategoryService;
import start.spring.basic.flowable.service.process.IWfProcessService;
import start.spring.basic.response.ResponseData;
import start.spring.basic.util.common.DateUtil;
import start.spring.basic.util.common.StringUtil;

/**
 * 请假Service业务层处理
 * 
 * @author xuyy
 * @date 2023-09-02
 */
@Service("leaveService")
public class BizLeaveServiceImpl extends FlowableBaseServiceImpl implements IBizLeaveService {
    
	//当前实现类的spring bean的name
	private static final String BEANNAME = "leaveService";
	
	//请假天数流程变量
    private static final String QJTS = "qjts";
	
	@Autowired
    private BizLeaveMapper bizLeaveMapper;
	
	@Autowired
    private WfApplyRecordMapper wfApplyRecordMapper;
	
	@Autowired
	private IWfCategoryService wfCategoryService;
    
    @Autowired
    private IWfProcessService processService;

	@Override
	public BizLeave selectDetailById(String id) {
		BizLeave bizLeave = null;
		if(!StringUtil.isEmpty(id)) {
			QueryWrapper<BizLeave> queryWrapper = new QueryWrapper<>();
	        queryWrapper.lambda().eq(BizLeave::getId, id);
	        bizLeave = this.bizLeaveMapper.selectOne(queryWrapper);
		}
        return bizLeave;
	}

    /**
     * 新增请假
     * 
     * @param bizLeave 请假
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseData<String> insertBizLeave(String tjzt, BizLeave bizLeave) {
    	
    	if(bizLeave!=null) {
    		ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(bizLeave.getDefinitionId())
                    .deploymentId(bizLeave.getDeployId()).singleResult();
            if (ObjectUtil.isNotNull(procDef) && procDef.isSuspended()) {
            	return ResponseData.errorMsg("流程已被挂起，无法申请！");
            }
            
            double hoursDis = DateUtil.hoursBetween(bizLeave.getKssj(),bizLeave.getJssj());
        	int qjts = (int) (hoursDis/24);
        	qjts++;
        	
        	//摘要
        	String summary = super.getSysUser().getDept().getDeptName() + super.getSysUser().getNickName() + "请假" + qjts + "天！";
            
    		//首次提交
    		if(bizLeave.getId()==null) {
    			
    	        String bussinessKey = super.idGenerator.nextId();
    			//保存业务表
            	bizLeave.setId(bussinessKey);
            	bizLeave.setUserId(String.valueOf(super.getSysUser().getUserId()));
            	bizLeave.setUserName(super.getSysUser().getNickName());
            	bizLeave.setQjsj(new Date());
            	this.bizLeaveMapper.insert(bizLeave);
            	
            	//获取流程分类
            	Long categoryId = Long.parseLong(procDef.getCategory());
            	WfCategory wfCategory = new WfCategory();
            	wfCategory.setCategoryId(categoryId);
            	List<WfCategory> wfCategoryList = wfCategoryService.selectWfCategoryList(wfCategory);
            	String categoryName = wfCategoryList.get(0).getCategoryName();
            	
            	//获取表单信息
            	WfDeployForm wfDeployForm = processService.selectDeployExternalForm(bizLeave.getDefinitionId(), bizLeave.getDeployId());
            	
            	//保存申请记录表
            	WfApplyRecord wfApplyRecord = new WfApplyRecord();
            	wfApplyRecord.setId(super.idGenerator.nextId());
            	wfApplyRecord.setUserId(super.getSysUser().getUserId());
            	wfApplyRecord.setUserName(super.getSysUser().getUserName());
            	wfApplyRecord.setNickName(super.getSysUser().getNickName());
            	wfApplyRecord.setDeptIds(super.getSysUser().getDeptId().toString());
            	wfApplyRecord.setDeptNames(super.getSysUser().getDept().getDeptName());
            	wfApplyRecord.setCategoryId(categoryId);
            	wfApplyRecord.setCategoryName(categoryName);
            	wfApplyRecord.setDefinitionId(bizLeave.getDefinitionId());
            	wfApplyRecord.setDefinitionName(procDef.getName());
            	wfApplyRecord.setDefinitionVersion(procDef.getVersion());
            	wfApplyRecord.setDeployId(bizLeave.getDeployId());
            	wfApplyRecord.setFormId(Long.parseLong(wfDeployForm.getFormKey().substring(4)));
            	wfApplyRecord.setBusinessKey(bussinessKey);
            	wfApplyRecord.setSummary(summary);
            	wfApplyRecord.setApprovalStatus(tjzt);
            	wfApplyRecord.setBeanName(BEANNAME);
            	this.wfApplyRecordMapper.insert(wfApplyRecord);
            	
    		}else {
    			BizLeave dbBizLeave = selectDetailById(bizLeave.getId());
    			//记录存在且申请人为当前登录人，可以更新
    			if(dbBizLeave!=null&&dbBizLeave.getUserId().equals(
    					String.valueOf(super.getSysUser().getUserId()))) {
    				//更新业务表
    				this.bizLeaveMapper.updateById(bizLeave);
    				
    				//更新摘要
    				WfApplyRecord wfApplyRecord = new WfApplyRecord();
    				wfApplyRecord.setSummary(summary);
    				
    				UpdateWrapper<WfApplyRecord> updateWrapper = new UpdateWrapper<>();
    				updateWrapper.lambda()
    								.eq(WfApplyRecord::getUserId, super.getSysUser().getUserId())
    								.eq(WfApplyRecord::getBusinessKey, bizLeave.getId());
    				this.wfApplyRecordMapper.update(wfApplyRecord, updateWrapper);
    			}else {
    				//记录不存在
    				if(ApprovalStatus.RUNNING.getStatus().equals(tjzt)) {
    					return ResponseData.errorMsg("未查询到申请记录，不可提交，请重新填写申请单！");
    				}else if(ApprovalStatus.DRAFT.getStatus().equals(tjzt)) {
    					return ResponseData.errorMsg("未查询到申请记录，不可更新草稿，请重新填写申请单！");
    				}else {
    					return ResponseData.error(ServiceEnum.REQUEST_INVALID.getCode(), ServiceEnum.REQUEST_INVALID.getDesc());
    				}
    			}
    		}
        	
        	//提交时启动流程，保存草稿时不启动
        	if(ApprovalStatus.RUNNING.getStatus().equals(tjzt)) {
        		Map<String, Object> variables =  new HashMap<>();
            	
            	variables.put(QJTS, qjts);
            	variables.put(ProcessConstants.PROCESS_APPLY_SUMMARY, summary);
            	
            	this.processService.startProcessInstance(bizLeave.getDefinitionId(), bizLeave.getId(), variables);
            	
            	return ResponseData.successMsg("申请已提交!");
        	}else {
        		return ResponseData.successMsg("草稿已保存！");
        	}
    	}else {
    		return ResponseData.errorMsg("申请单为空，不可提交，请填写申请单！");
    	}
    	
    }

    /**
     * 批量删除请假
     * 
     * @param ids 需要删除的请假主键
     * @return 结果
     */
    @Override
    public ResponseData<String> deleteBizLeaveByIds(List<String> ids) {
    	
    	QueryWrapper<BizLeave> queryWrapper = new QueryWrapper<>();
    	queryWrapper.lambda().eq(BizLeave::getUserId, super.getSysUser().getUserId())
    						.in(BizLeave::getId, ids);
    	this.bizLeaveMapper.delete(queryWrapper);
    	
    	return ResponseData.successMsg("已删除!");
    }

	@Override
	public void handleDelete(List<String> businessKeyList) {
		this.deleteBizLeaveByIds(businessKeyList);
	}
}
